home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / PIL / SpiderImagePlugin.py < prev    next >
Text File  |  2006-12-03  |  9KB  |  295 lines

  1. #
  2. # The Python Imaging Library.
  3. #
  4. # SPIDER image file handling
  5. #
  6. # History:
  7. # 2004-08-02    Created BB
  8. # 2006-03-02    added save method
  9. # 2006-03-13    added support for stack images
  10. #
  11. # Copyright (c) 2004 by Health Research Inc. (HRI) RENSSELAER, NY 12144.
  12. # Copyright (c) 2004 by William Baxter.
  13. # Copyright (c) 2004 by Secret Labs AB.
  14. # Copyright (c) 2004 by Fredrik Lundh.
  15. #
  16.  
  17. ##
  18. # Image plugin for the Spider image format.  This format is is used
  19. # by the SPIDER software, in processing image data from electron
  20. # microscopy and tomography.
  21. ##
  22.  
  23. #
  24. # SpiderImagePlugin.py
  25. #
  26. # The Spider image format is used by SPIDER software, in processing
  27. # image data from electron microscopy and tomography.
  28. #
  29. # Spider home page:
  30. # http://www.wadsworth.org/spider_doc/spider/docs/spider.html
  31. #
  32. # Details about the Spider image format:
  33. # http://www.wadsworth.org/spider_doc/spider/docs/image_doc.html
  34. #
  35.  
  36. import Image, ImageFile
  37. import os, string, struct, sys
  38.  
  39. def isInt(f):
  40.     try:
  41.         i = int(f)
  42.         if f-i == 0: return 1
  43.         else:        return 0
  44.     except:
  45.         return 0
  46.  
  47. iforms = [1,3,-11,-12,-21,-22]
  48.  
  49. # There is no magic number to identify Spider files, so just check a
  50. # series of header locations to see if they have reasonable values.
  51. # Returns no.of bytes in the header, if it is a valid Spider header,
  52. # otherwise returns 0
  53.  
  54. def isSpiderHeader(t):
  55.     h = (99,) + t   # add 1 value so can use spider header index start=1
  56.     # header values 1,2,5,12,13,22,23 should be integers
  57.     for i in [1,2,5,12,13,22,23]:
  58.         if not isInt(h[i]): return 0
  59.     # check iform
  60.     iform = int(h[5])
  61.     if not iform in iforms: return 0
  62.     # check other header values
  63.     labrec = int(h[13])   # no. records in file header
  64.     labbyt = int(h[22])   # total no. of bytes in header
  65.     lenbyt = int(h[23])   # record length in bytes
  66.     #print "labrec = %d, labbyt = %d, lenbyt = %d" % (labrec,labbyt,lenbyt)
  67.     if labbyt != (labrec * lenbyt): return 0
  68.     # looks like a valid header
  69.     return labbyt
  70.  
  71. def isSpiderImage(filename):
  72.     fp = open(filename,'rb')
  73.     f = fp.read(92)   # read 23 * 4 bytes
  74.     fp.close()
  75.     bigendian = 1
  76.     t = struct.unpack('>23f',f)    # try big-endian first
  77.     hdrlen = isSpiderHeader(t)
  78.     if hdrlen == 0:
  79.         bigendian = 0
  80.         t = struct.unpack('<23f',f)  # little-endian
  81.         hdrlen = isSpiderHeader(t)
  82.     return hdrlen
  83.  
  84.  
  85. class SpiderImageFile(ImageFile.ImageFile):
  86.  
  87.     format = "SPIDER"
  88.     format_description = "Spider 2D image"
  89.  
  90.     def _open(self):
  91.         # check header
  92.         n = 27 * 4  # read 27 float values
  93.         f = self.fp.read(n)
  94.  
  95.         try:
  96.             self.bigendian = 1
  97.             t = struct.unpack('>27f',f)    # try big-endian first
  98.             hdrlen = isSpiderHeader(t)
  99.             if hdrlen == 0:
  100.                 self.bigendian = 0
  101.                 t = struct.unpack('<27f',f)  # little-endian
  102.                 hdrlen = isSpiderHeader(t)
  103.             if hdrlen == 0:
  104.                 raise SyntaxError, "not a valid Spider file"
  105.         except struct.error:
  106.             raise SyntaxError, "not a valid Spider file"
  107.  
  108.         h = (99,) + t   # add 1 value : spider header index starts at 1
  109.         iform = int(h[5])
  110.         if iform != 1:
  111.             raise SyntaxError, "not a Spider 2D image"
  112.  
  113.         self.size = int(h[12]), int(h[2]) # size in pixels (width, height)
  114.         self.istack = int(h[24])
  115.         self.imgnumber = int(h[27])
  116.  
  117.         if self.istack == 0 and self.imgnumber == 0:
  118.             # stk=0, img=0: a regular 2D image
  119.             offset = hdrlen
  120.             self.nimages = 1
  121.         elif self.istack > 0 and self.imgnumber == 0:
  122.             # stk>0, img=0: Opening the stack for the first time
  123.             self.imgbytes = int(h[12]) * int(h[2]) * 4
  124.             self.hdrlen = hdrlen
  125.             self.nimages = int(h[26])
  126.             # Point to the first image in the stack
  127.             offset = hdrlen * 2
  128.             self.imgnumber = 1
  129.         elif self.istack == 0 and self.imgnumber > 0:
  130.             # stk=0, img>0: an image within the stack
  131.             offset = hdrlen + self.stkoffset
  132.             self.istack = 2  # So Image knows it's still a stack
  133.         else:
  134.             raise SyntaxError, "inconsistent stack header values"
  135.  
  136.         if self.bigendian:
  137.             self.rawmode = "F;32BF"
  138.         else:
  139.             self.rawmode = "F;32F"
  140.         self.mode = "F"
  141.  
  142.         self.tile = [("raw", (0, 0) + self.size, offset,
  143.                     (self.rawmode, 0, 1))]
  144.         self.__fp = self.fp # FIXME: hack
  145.  
  146.     # 1st image index is zero (although SPIDER imgnumber starts at 1)
  147.     def tell(self):
  148.         if self.imgnumber < 1:
  149.             return 0
  150.         else:
  151.             return self.imgnumber - 1
  152.  
  153.     def seek(self, frame):
  154.         if self.istack == 0:
  155.             return
  156.         if frame >= self.nimages:
  157.             raise EOFError, "attempt to seek past end of file"
  158.         self.stkoffset = self.hdrlen + frame * (self.hdrlen + self.imgbytes)
  159.         self.fp = self.__fp
  160.         self.fp.seek(self.stkoffset)
  161.         self._open()
  162.  
  163.     # returns a byte image after rescaling to 0..255
  164.     def convert2byte(self, depth=255):
  165.         (min, max) = self.getextrema()
  166.         m = 1
  167.         if max != min:
  168.             m = depth / (max-min)
  169.         b = -m * min
  170.         return self.point(lambda i, m=m, b=b: i * m + b).convert("L")
  171.  
  172.     # returns a ImageTk.PhotoImage object, after rescaling to 0..255
  173.     def tkPhotoImage(self):
  174.         import ImageTk
  175.         return ImageTk.PhotoImage(self.convert2byte(), palette=256)
  176.  
  177. # --------------------------------------------------------------------
  178. # Image series
  179.  
  180. # given a list of filenames, return a list of images
  181. def loadImageSeries(filelist=None):
  182.     " create a list of Image.images for use in montage "
  183.     if filelist == None or len(filelist) < 1:
  184.         return
  185.  
  186.     imglist = []
  187.     for img in filelist:
  188.         if not os.path.exists(img):
  189.             print "unable to find %s" % img
  190.             continue
  191.         try:
  192.             im = Image.open(img).convert2byte()
  193.         except:
  194.             if not isSpiderImage(img):
  195.                 print img + " is not a Spider image file"
  196.             continue
  197.         im.info['filename'] = img
  198.         imglist.append(im)
  199.     return imglist
  200.  
  201. # --------------------------------------------------------------------
  202. # For saving images in Spider format
  203.  
  204. def makeSpiderHeader(im):
  205.     nsam,nrow = im.size
  206.     lenbyt = nsam * 4  # There are labrec records in the header
  207.     labrec = 1024 / lenbyt
  208.     if 1024%lenbyt != 0: labrec += 1
  209.     labbyt = labrec * lenbyt
  210.     hdr = []
  211.     nvalues = labbyt / 4
  212.     for i in range(nvalues):
  213.         hdr.append(0.0)
  214.  
  215.     if len(hdr) < 23:
  216.         return []
  217.  
  218.     # NB these are Fortran indices
  219.     hdr[1]  = 1.0           # nslice (=1 for an image)
  220.     hdr[2]  = float(nrow)   # number of rows per slice
  221.     hdr[5]  = 1.0           # iform for 2D image
  222.     hdr[12] = float(nsam)   # number of pixels per line
  223.     hdr[13] = float(labrec) # number of records in file header
  224.     hdr[22] = float(labbyt) # total number of bytes in header
  225.     hdr[23] = float(lenbyt) # record length in bytes
  226.  
  227.     # adjust for Fortran indexing
  228.     hdr = hdr[1:]
  229.     hdr.append(0.0)
  230.     # pack binary data into a string
  231.     hdrstr = []
  232.     for v in hdr:
  233.         hdrstr.append(struct.pack('f',v))
  234.     return hdrstr
  235.  
  236. def _save(im, fp, filename):
  237.     if im.mode[0] != "F":
  238.         im = im.convert('F')
  239.  
  240.     hdr = makeSpiderHeader(im)
  241.     if len(hdr) < 256:
  242.         raise IOError, "Error creating Spider header"
  243.  
  244.     # write the SPIDER header
  245.     try:
  246.         fp = open(filename, 'wb')
  247.     except:
  248.         raise IOError, "Unable to open %s for writing" % filename
  249.     fp.writelines(hdr)
  250.  
  251.     rawmode = "F;32NF"  #32-bit native floating point
  252.     ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode,0,1))])
  253.  
  254.     fp.close()
  255.  
  256. def _save_spider(im, fp, filename):
  257.     # get the filename extension and register it with Image
  258.     fn, ext = os.path.splitext(filename)
  259.     Image.register_extension("SPIDER", ext)
  260.     _save(im, fp, filename)
  261.  
  262. # --------------------------------------------------------------------
  263.  
  264. Image.register_open("SPIDER", SpiderImageFile)
  265. Image.register_save("SPIDER", _save_spider)
  266.  
  267. if __name__ == "__main__":
  268.  
  269.     if not sys.argv[1:]:
  270.         print "Syntax: python SpiderImagePlugin.py Spiderimage [outfile]"
  271.         sys.exit()
  272.  
  273.     filename = sys.argv[1]
  274.     if not isSpiderImage(filename):
  275.         print "input image must be in Spider format"
  276.         sys.exit()
  277.  
  278.     outfile = ""
  279.     if len(sys.argv[1:]) > 1:
  280.         outfile = sys.argv[2]
  281.  
  282.     im = Image.open(filename)
  283.     print "image: " + str(im)
  284.     print "format: " + str(im.format)
  285.     print "size: " + str(im.size)
  286.     print "mode: " + str(im.mode)
  287.     print "max, min: ",
  288.     print im.getextrema()
  289.  
  290.     if outfile != "":
  291.         # perform some image operation
  292.         im = im.transpose(Image.FLIP_LEFT_RIGHT)
  293.         print "saving a flipped version of %s as %s " % (os.path.basename(filename), outfile)
  294.         im.save(outfile, "SPIDER")
  295.